<?php

Class PayoutMethod extends DataObject {
    private static $supported_methods = array('BankWirePayoutMethod' => true);

    private static $processing_fee = array('BankWirePayoutMethod' => 20);

    private static $processing_fee_percentage = array('BankWirePayoutMethod' => 0);

    private static $db = array(
        'Amount' => 'Currency',
        'ProcessingFee' => 'Currency',
        'Reference' => 'Varchar'
    );
	
	static function get_supported_methods() {
    	$methods = Config::inst()->get('PayoutMethod', 'supported_methods');
    	foreach($methods as $code => $active){
    		if($active && ClassInfo::exists($code)){
    			$methods[$code] = singleton($code)->i18n_singular_name();
			}
			else{
				unset($methods[$code]);
			}
    	}
        return $methods;
    }
	
	static function add_supported_methods($method) {
        Config::inst()->update('PayoutMethod', 'supported_methods', array($method => true));
    }
    
    static function remove_supported_methods($method) {
    	Config::inst()->remove('PayoutMethod', 'supported_methods', $method);
    }

    static function set_processing_fee($fee) {
        Config::inst()->update('PayoutMethod', 'processing_fee', $fee);
    }

    static function get_processing_fee($payoutmethod) {
        $processing_fee = Config::inst()->get('PayoutMethod', 'processing_fee');
        return isset($processing_fee[$payoutmethod]) ? $processing_fee[$payoutmethod] : 0;
    }

    static function set_processing_fee_percentage($percentage) {
        Config::inst()->update('PayoutMethod', 'processing_fee_percentage', $percentage);
    }

    static function get_processing_fee_percentage($payoutmethod) {
        $processing_fee_percentage = Config::inst()->get('PayoutMethod', 'processing_fee_percentage');
        return isset($processing_fee_percentage[$payoutmethod]) ? $processing_fee_percentage[$payoutmethod] : 0;
    }

    static function combined_form_fields($fields, $memberid) {
        $support_methods = self::get_supported_methods();
        $fields->push(PayoutSetField::create('PayoutMethod', _t('PayoutMethod.PAYOUT_TYPE', 'Payout Type'), $support_methods));
        foreach($support_methods as $methodClass => $title) {
            $setFields = new FieldList();
            $processing_fee = PayoutMethod::get_processing_fee($methodClass);
            $processing_fee_percentage = PayoutMethod::get_processing_fee_percentage($methodClass);
            if($processing_fee > 0 || $processing_fee_percentage > 0) {
                $setFields->push(HiddenField::create(sprintf('%s_ProcessingFee', $methodClass), 'ProcessingFee', $processing_fee)->addExtraClass('processing_fee')->setAttribute('rel', 'processing_fee'));
                $setFields->push(HiddenField::create(sprintf('%s_ProcessingFeePercentage', $methodClass), 'ProcessingFeePercentage', $processing_fee_percentage)->addExtraClass('processing_fee_percentage')->setAttribute('rel', 'processing_fee_percentage'));
				Requirements::javascript('account/javascript/PayoutProcessingFee.min.js');
				
                if($processing_fee > 0 && $processing_fee_percentage > 0) {
                    $setFields->push(TextField::create(sprintf('%s_ShowProcessingFee', $methodClass), _t('PayoutMethod.PROCESSING_FEE', 'Processing Fee'))->addExtraClass('show_processing_fee')->setAttribute('rel', 'show_processing_fee')->setAttribute('style', 'max-width: 150px;')->setAttribute('data-prefix', Config::inst()->get('Currency', 'currency_symbol'))->setReadonly(true)->setDescription(sprintf('%s / %s', DBField::create_field('Currency', $processing_fee)->Nice(), DBField::create_field('Percentage', $processing_fee_percentage)->Nice())));
                } else if($processing_fee_percentage > 0) {
                    $setFields->push(TextField::create(sprintf('%s_ShowProcessingFee', $methodClass), _t('PayoutMethod.PROCESSING_FEE', 'Processing Fee'))->addExtraClass('show_processing_fee')->setAttribute('rel', 'show_processing_fee')->setAttribute('style', 'max-width: 150px;')->setAttribute('data-prefix', Config::inst()->get('Currency', 'currency_symbol'))->setReadonly(true)->setDescription(sprintf('%s', DBField::create_field('Percentage', $processing_fee_percentage)->Nice())));
                } else {
                    $setFields->push(TextField::create(sprintf('%s_ShowProcessingFee', $methodClass), _t('PayoutMethod.PROCESSING_FEE', 'Processing Fee'), DBField::create_field('Currency', $processing_fee)->Nice())->addExtraClass('show_processing_fee')->setAttribute('rel', 'show_processing_fee')->setAttribute('style', 'max-width: 150px;')->setReadonly(true));
                }
            }

            $setFields->merge($methodClass::create()->getPayoutFormFields($memberid));
			$methodFields = CompositeField::create($setFields)->addExtraClass('payoutfields')->addExtraClass('hidden')->addExtraClass($methodClass);
			
            $fields->push($methodFields);
        }

        $fields->push(SecurityPinField::create('PayoutMethodSecurityPin', _t('PayoutMethod.SECURITY_PIN', 'Security Pin')));

        return $fields;
    }

    /**
     * Return the form requirements for all the payout methods.
     *
     * @return An array suitable for passing to RequiredFields
     */
    static function payout_requirements(&$validator, $data, $method) {
        $methods = self::get_supported_methods();
        if(isset($methods[$method])) {
            $validator = $method::create()->getPayoutFormRequirements($validator, $data);
        }
    }

    /**
     * Generate reference for payout method
     * @return str Returns the reference
     */
    static function reference_generator() {
        $reference = rand(1, 99999999);
        $reference = str_pad($reference, 8, "0", STR_PAD_LEFT);
        while(DB::query("select ID from PayoutMethod where Reference = '" . $reference . "'")->value()) {
            $reference = rand(1, 999999999);
            $reference = str_pad($reference, 8, "0", STR_PAD_LEFT);
        }
        return $reference;
    }

    public function fieldLabels($includerelations = true) {
        $labels = parent::fieldLabels($includerelations);

        $labels['ProcessingFee'] = _t('PayoutMethod.PROCESSING_FEE', 'Processing Fee');
        $labels['Reference'] = _t('PayoutMethod.REFERENCE', 'Reference');

        return $labels;
    }

    function getTitle() {
        $supported_methods = self::get_supported_methods();
        if(isset($supported_methods[$this->ClassName])) {
            return $supported_methods[$this->ClassName];
        }
    }

    function getFrontEndFields($params = null) {
        $fields = parent::getFrontendFields($params);
        $fields->removeByName('ProcessingFee');
        $fields->removeByName('Reference');
        $fields->removeByName('Amount');
        return $fields;
    }

    function getPayoutFormFields($memberid) {
        return $this->getFrontendFields();
    }

    function getPayoutFormRequirements($validator, $data) {
        return $validator;
    }

    function onBeforeWrite() {
        parent::onBeforeWrite();

        if($this->Reference == '') {
            $this->Reference = PayoutMethod::reference_generator();
        }

        if($this->ProcessingFeePercentage && $this->Amount * $this->ProcessingFeePercentage > $this->ProcessingFee) {
            $this->ProcessingFee = $this->Amount * $this->ProcessingFeePercentage;
        }
		
		if($this->ProcessingFee > 0){
			$this->Amount = $this->Amount - $this->ProcessingFee;
		}
    }

    function getFullDetailHTML() {
        return $this->renderWith($this->class);
    }

	function canView($member = false) {
        return false;
    }

    function canEdit($member = false) {
        return false;
    }

    function canDelete($member = false) {
        return false;
    }

    function canCreate($member = false) {
        return false;
    }
}

class PayoutMethod_Validator extends RequiredFields {
    function php($data) {
        $valid = parent::php($data);

        // check current member id
        $isValid = (Distributor::currentUserID() == $data['MemberID']);
        if(!$isValid) {
            $this->validationError('Error', _t('PayoutMethod.PAYOUT_PROCESS_ERROR', 'Error occur while processing payout request. Please contact our administrator for further information.'), 'warning');
        } else {
            $balance = Account::get($data['AccountClass'], $data['MemberID'])->Balance;
            if($data['Amount'] > $balance) {
                $this->validationError('Error', _t('PayoutMethod.INSUFFICIENT_BALANCE', 'Insufficient account balance ({balance})', 'Display insufficient account balance', array('balance' => Account::get($data['AccountClass'], $data['MemberID'])->obj('Balance')->Nice())), 'warning');
            }

            PayoutMethod::payout_requirements($this, $data, $data['PayoutMethod']);
        }
        return $this->getErrors();
    }

}
?>